home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nothing but Tetris
/
Nothing but Tetris.iso
/
amiga
/
workbench_tris
/
key_input.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-19
|
6KB
|
191 lines
/*
Copyright (c) 1992, Trevor Smigiel. All rights reserved.
(I hope Commodore doesn't mind that I borrowed their copyright notice.)
The source and executable code of this program may only be distributed in free
electronic form, via bulletin board or as part of a fully non-commercial and
freely redistributable diskette. Both the source and executable code (including
comments) must be included, without modification, in any copy. This example may
not be published in printed form or distributed with any commercial product.
This program is provided "as-is" and is subject to change; no warranties are
made. All use is at your own risk. No liability or responsibility is assumed.
*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/tasks.h>
#include <devices/inputevent.h>
#include <devices/input.h>
#include <dos/dos.h>
/* */
#include <proto/exec.h>
#include "con_input.h"
struct InputEvent *__asm __interrupt
KeyWatch(
register __a0 struct InputEvent *inputEvents,
register __a1 struct ControlData *handlerData
)
{
struct InputEvent *ie = inputEvents;
struct InputEvent *pie = (struct InputEvent *)&ie;
char *key = handlerData->cd_Keys;
ULONG s = 0,
b;
if (key) while (inputEvents) {
if (inputEvents->ie_Class == IECLASS_RAWKEY) {
for (b = 1; *key; key++, b <<= 1) {
if (inputEvents->ie_Code & IECODE_UP_PREFIX) {
if ((inputEvents->ie_Code & ~IECODE_UP_PREFIX) == *key) {
pie->ie_NextEvent = inputEvents->ie_NextEvent;
inputEvents = pie;
handlerData->cd_State &= ~b;
}
} else {
if (inputEvents->ie_Code == *key) {
pie->ie_NextEvent = inputEvents->ie_NextEvent;
inputEvents = pie;
if (!(handlerData->cd_State & b)) {
s = 1;
handlerData->cd_State |= b;
}
}
}
}
}
pie = inputEvents;
inputEvents = inputEvents->ie_NextEvent;
}
if (s)
Signal(handlerData->cd_Task, SIGBREAKF_CTRL_F);
return ie;
}
void
KeyTask(void)
{
struct MsgPort *ReplyPort;
struct MsgPort *timerPort;
struct MsgPort *inputPort;
struct IOStdReq *inputReqBlk;
struct Interrupt *inputHandler;
struct timerequest *timerReqBlk;
struct Task *ThisTask;
struct ControlData *cd;
struct ControlMsg CMsg;
ULONG signaled, signals, PortSig, tPortSig;
char *keys;
Wait(SIGBREAKF_CTRL_F); /* Wait for parent to tell us to go */
ThisTask = FindTask(NULL);
cd = (struct ControlData *) ThisTask->tc_UserData;
keys = cd->cd_Keys;
ReplyPort = CreateMsgPort();
if (ReplyPort) {
inputPort = CreateMsgPort();
if (inputPort) {
inputHandler = AllocMem(sizeof(struct Interrupt), MEMF_PUBLIC | MEMF_CLEAR);
if (inputHandler) {
inputReqBlk = CreateIORequest(inputPort, sizeof(struct IOStdReq));
if (inputReqBlk) {
if (!OpenDevice("input.device", NULL, (struct IORequest *) inputReqBlk, NULL)) {
inputHandler->is_Code = (void (*)()) KeyWatch;
inputHandler->is_Data = (APTR) cd; /* Get this info from task */
inputHandler->is_Node.ln_Pri = 100;
inputHandler->is_Node.ln_Name = "RawKeyHandler";
inputReqBlk->io_Data = (APTR) inputHandler;
inputReqBlk->io_Command = IND_ADDHANDLER;
DoIO((struct IORequest *) inputReqBlk);
CMsg.cm_Msg.mn_Node.ln_Type = NT_REPLYMSG;
CMsg.cm_Msg.mn_ReplyPort = ReplyPort;
CMsg.cm_Msg.mn_Length = sizeof(struct ControlMsg);
CMsg.cm_CData = cd;
timerPort = CreateMsgPort();
if (timerPort) {
timerReqBlk = (struct timerequest *) CreateIORequest(ReplyPort, sizeof(struct timerequest));
if (timerReqBlk) {
if (!OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest *)timerReqBlk, 0L)) {
/*
* There should be no reason for a user to
* send this task signals, so I figure it is
* safe to use the break sigs.
*/
tPortSig = (1 << timerPort->mp_SigBit);
PortSig = (1 << ReplyPort->mp_SigBit);
signals = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F | PortSig | tPortSig;
for (;;) {
signaled = Wait(signals);
if (signaled & SIGBREAKF_CTRL_D) cd->cd_Keys = NULL;
if (signaled & SIGBREAKF_CTRL_E) cd->cd_Keys = keys;
if (signaled & SIGBREAKF_CTRL_F) { /* Key pressed */
if (!CheckIO((struct IORequest *)timerReqBlk)) {
AbortIO((struct IORequest *)timerReqBlk);
WaitIO((struct IORequest *)timerReqBlk);
}
}
if (signaled & PortSig) while (GetMsg(ReplyPort));
if (signaled & tPortSig) while (GetMsg(timerPort));
if (signaled & SIGBREAKF_CTRL_C) break;
if ((CheckIO((struct IORequest *)timerReqBlk)) && (cd->cd_State)) {
timerReqBlk->tr_node.io_Command = TR_ADDREQUEST;
timerReqBlk->tr_time.tv_secs = 0;
timerReqBlk->tr_time.tv_micro = 100000;
SendIO((struct IORequest *)timerReqBlk);
Forbid();
if (CMsg.cm_Msg.mn_Node.ln_Type == NT_REPLYMSG) {
CMsg.cm_State = cd->cd_State;
PutMsg(cd->cd_MsgPort, (struct Message *)&CMsg);
}
Permit();
}
}
while (CMsg.cm_Msg.mn_Node.ln_Type != NT_REPLYMSG) {
while (GetMsg(ReplyPort));
}
if (!CheckIO((struct IORequest *)timerReqBlk)) {
AbortIO((struct IORequest *)timerReqBlk);
WaitIO((struct IORequest *)timerReqBlk);
}
CloseDevice((struct IORequest *) timerReqBlk);
}
DeleteIORequest((struct IORequest *) timerReqBlk);
}
DeleteMsgPort(timerPort);
}
inputReqBlk->io_Data = (APTR) inputHandler;
inputReqBlk->io_Command = IND_REMHANDLER;
DoIO((struct IORequest *) inputReqBlk);
CloseDevice((struct IORequest *) inputReqBlk);
}
DeleteIORequest((struct IORequest *) inputReqBlk);
}
FreeMem(inputHandler, sizeof(struct Interrupt));
}
DeleteMsgPort(inputPort);
}
DeleteMsgPort(ReplyPort);
}
Forbid();
cd->cd_MsgPort = NULL;
Signal(cd->cd_Parent, SIGBREAKF_CTRL_F);
Wait(0L);
}